/*
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2003-2007 Intel Corporation. All Rights Reserved.
//
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_DV_VIDEO_DECODER)

#include <ippvc.h>
#include "umc_dv_decoder.h"
#include "umc_dv_internal.h"
#include "vm_sys_info.h"

namespace UMC
{

//////////////////////////////////////////////////////////////////
// DV segment store functions

const Ipp32u lMacroBlockWidth420 = 8 * 2;
const Ipp32u lMacroBlockHeight420 = 8 * 2;
const Ipp32u lSuperBlockWidth420 = (lMacroBlockWidth420 * 9);
const Ipp32u lSuperBlockHeight420 = (lMacroBlockHeight420 * 3);

const Ipp32u lMacroBlockWidth411 = 8 * 4;
const Ipp32u lMacroBlockHeight411 = 8;
const Ipp32u lSuperBlockHeight411 = (lMacroBlockHeight411 * 6);

void DVVideoDecoder::InitializeStoreDVSDInfo(STORE_DV_SEGMENT_INFO &StoreInfo,
                                             Ipp32u i,
                                             Ipp32u k,
                                             Ipp32u nThreadNum)
{
    Ipp16u *lpsBlock = m_ppShortBlocks[nThreadNum];

    StoreInfo.m_lPitch = m_nPitch;

    // fill system 625 store info
    if (SYSTEM_625 == m_nSystem)
    {
        Ipp32u lRow, lCol, lBytesPerPixel = 0;

        // get current column
        lCol = k / 3;

        // get current row
        if (lCol & 0x01)
            lRow = 2 - (k % 3);
        else
            lRow = (k % 3);

        // we use following formula:
        // dest buffer +
        // needed super block row offset +
        // needed super block column offset +
        // needed macro block row offset +
        // needed macro block column offset

        lBytesPerPixel = 2;
        StoreInfo.m_lpsSource[0] = lpsBlock + (6 * 64 * 0);
        StoreInfo.m_lpbDestination[0] = m_lpDestination +
                                        (((i + 2) % 12) * m_nPitch * lSuperBlockHeight420 +
                                        m_nPitch * lMacroBlockHeight420 * lRow +
                                        ((2) * lSuperBlockWidth420 +
                                        lMacroBlockWidth420 * lCol) * lBytesPerPixel) / m_lSizeSubSampled;

        StoreInfo.m_lpsSource[1] = lpsBlock + (6 * 64 * 1);
        StoreInfo.m_lpbDestination[1] = m_lpDestination +
                                        (((i + 6) % 12) * m_nPitch * lSuperBlockHeight420 +
                                        m_nPitch * lMacroBlockHeight420 * lRow +
                                        ((1) * lSuperBlockWidth420 +
                                        lMacroBlockWidth420 * lCol) * lBytesPerPixel) / m_lSizeSubSampled;

        StoreInfo.m_lpsSource[2] = lpsBlock + (6 * 64 * 2);
        StoreInfo.m_lpbDestination[2] = m_lpDestination +
                                        (((i + 8) % 12) * m_nPitch * lSuperBlockHeight420 +
                                        m_nPitch * lMacroBlockHeight420 * lRow +
                                        ((3) * lSuperBlockWidth420 +
                                        lMacroBlockWidth420 * lCol) * lBytesPerPixel) / m_lSizeSubSampled;

        StoreInfo.m_lpsSource[3] = lpsBlock + (6 * 64 * 3);
        StoreInfo.m_lpbDestination[3] = m_lpDestination +
                                        (((i + 0) % 12) * m_nPitch * lSuperBlockHeight420 +
                                        m_nPitch * lMacroBlockHeight420 * lRow +
                                        ((0) * lSuperBlockWidth420 +
                                        lMacroBlockWidth420 * lCol) * lBytesPerPixel) / m_lSizeSubSampled;

        StoreInfo.m_lpsSource[4] = lpsBlock + (6 * 64 * 4);
        StoreInfo.m_lpbDestination[4] = m_lpDestination +
                                        (((i + 4) % 12) * m_nPitch * lSuperBlockHeight420 +
                                        m_nPitch * lMacroBlockHeight420 * lRow +
                                        ((4) * lSuperBlockWidth420 +
                                        lMacroBlockWidth420 * lCol) * lBytesPerPixel) / m_lSizeSubSampled;
    }
    // fill system 525 store info
    else
    {
        Ipp32u lRowA, lRowB, lRowC, lColA, lColB, lBytesPerPixel = 0;

        // get current column
        lColA = k / 6;
        lColB = (k + 3) / 6;

        // get current row
        if (lColA & 0x01)
            lRowC = lRowA = 5 - (k % 6);
        else
            lRowC = lRowA = (k % 6);

        if (lColB & 0x01)
            lRowB = 5 - ((k + 3) % 6);
        else
            lRowB = ((k + 3) % 6);

        if (24 < k)
            lRowC += (k - 24);

        // we use following formula:
        // dest buffer +
        // needed super block row offset +
        // needed super block column offset +
        // needed macro block row offset +
        // needed macro block column offset
        lBytesPerPixel = 2;
        StoreInfo.m_lpsSource[0] = lpsBlock + (6 * 64 * 0);
        StoreInfo.m_lpbDestination[0] = m_lpDestination +
                                        (((i + 2) % 10) * m_nPitch * lSuperBlockHeight411 +
                                        m_nPitch * lMacroBlockHeight411 * lRowA +
                                        ((9) * lMacroBlockWidth411 +
                                        lMacroBlockWidth411 * lColA) * lBytesPerPixel) / m_lSizeSubSampled;

        StoreInfo.m_lpsSource[1] = lpsBlock + (6 * 64 * 1);
        StoreInfo.m_lpbDestination[1] = m_lpDestination +
                                        (((i + 6) % 10) * m_nPitch * lSuperBlockHeight411 +
                                        m_nPitch * lMacroBlockHeight411 * lRowB +
                                        ((4) * lMacroBlockWidth411 +
                                        lMacroBlockWidth411 * lColB) * lBytesPerPixel) / m_lSizeSubSampled;

        StoreInfo.m_lpsSource[2] = lpsBlock + (6 * 64 * 2);
        StoreInfo.m_lpbDestination[2] = m_lpDestination +
                                        (((i + 8) % 10) * m_nPitch * lSuperBlockHeight411 +
                                        m_nPitch * lMacroBlockHeight411 * lRowB +
                                        ((13) * lMacroBlockWidth411 +
                                        lMacroBlockWidth411 * lColB) * lBytesPerPixel) / m_lSizeSubSampled;

        StoreInfo.m_lpsSource[3] = lpsBlock + (6 * 64 * 3);
        StoreInfo.m_lpbDestination[3] = m_lpDestination +
                                        (((i + 0) % 10) * m_nPitch * lSuperBlockHeight411 +
                                        m_nPitch * lMacroBlockHeight411 * lRowA +
                                        ((0) * lMacroBlockWidth411 +
                                        lMacroBlockWidth411 * lColA) * lBytesPerPixel) / m_lSizeSubSampled;

        StoreInfo.m_lpsSource[4] = lpsBlock + (6 * 64 * 4);
        StoreInfo.m_lpbDestination[4] = m_lpDestination +
                                        (((i + 4) % 10) * m_nPitch * lSuperBlockHeight411 +
                                        m_nPitch * lMacroBlockHeight411 * lRowC +
                                        ((18) * lMacroBlockWidth411 +
                                        lMacroBlockWidth411 * lColA) * lBytesPerPixel) / m_lSizeSubSampled;
    }

} // void DVVideoDecoder::InitializeStoreDVSDInfo(STORE_DV_SEGMENT_INFO &StoreInfo,

void DVVideoDecoder::InitializeStoreDV25Info(STORE_DV_SEGMENT_INFO &StoreInfo,
                                             Ipp32u i,
                                             Ipp32u k,
                                             Ipp32u nThreadNum)
{
    Ipp16u *lpsBlock = m_ppShortBlocks[nThreadNum];
    Ipp32u lRowA, lRowB, lRowC, lColA, lColB, lBytesPerPixel = 0;
    StoreInfo.m_lPitch = m_nPitch;

    // get current column
    lColA = k / 6;
    lColB = (k + 3) / 6;

    // get current row
    if (lColA & 0x01)
        lRowC = lRowA = 5 - (k % 6);
    else
        lRowC = lRowA = (k % 6);

    if (lColB & 0x01)
        lRowB = 5 - ((k + 3) % 6);
    else
        lRowB = ((k + 3) % 6);

    if (24 < k)
        lRowC += (k - 24);

    // we use following formula:
    // dest buffer +
    // needed super block row offset +
    // needed super block column offset +
    // needed macro block row offset +
    // needed macro block column offset

    lBytesPerPixel = 2;
    StoreInfo.m_lpsSource[0] = lpsBlock + (6 * 64 * 0);
    StoreInfo.m_lpbDestination[0] = m_lpDestination +
                                    (((i + 2) % m_nMaxNumberOfDIFSequences) * m_nPitch * lSuperBlockHeight411 +
                                    m_nPitch * lMacroBlockHeight411 * lRowA +
                                    ((9) * lMacroBlockWidth411 +
                                    lMacroBlockWidth411 * lColA) * lBytesPerPixel) / m_lSizeSubSampled;

    StoreInfo.m_lpsSource[1] = lpsBlock + (6 * 64 * 1);
    StoreInfo.m_lpbDestination[1] = m_lpDestination +
                                    (((i + 6) % m_nMaxNumberOfDIFSequences) * m_nPitch * lSuperBlockHeight411 +
                                    m_nPitch * lMacroBlockHeight411 * lRowB +
                                    ((4) * lMacroBlockWidth411 +
                                    lMacroBlockWidth411 * lColB) * lBytesPerPixel) / m_lSizeSubSampled;

    StoreInfo.m_lpsSource[2] = lpsBlock + (6 * 64 * 2);
    StoreInfo.m_lpbDestination[2] = m_lpDestination +
                                    (((i + 8) % m_nMaxNumberOfDIFSequences) * m_nPitch * lSuperBlockHeight411 +
                                    m_nPitch * lMacroBlockHeight411 * lRowB +
                                    ((13) * lMacroBlockWidth411 +
                                    lMacroBlockWidth411 * lColB) * lBytesPerPixel) / m_lSizeSubSampled;

    StoreInfo.m_lpsSource[3] = lpsBlock + (6 * 64 * 3);
    StoreInfo.m_lpbDestination[3] = m_lpDestination +
                                    (((i + 0) % m_nMaxNumberOfDIFSequences) * m_nPitch * lSuperBlockHeight411 +
                                    m_nPitch * lMacroBlockHeight411 * lRowA +
                                    ((0) * lMacroBlockWidth411 +
                                    lMacroBlockWidth411 * lColA) * lBytesPerPixel) / m_lSizeSubSampled;

    StoreInfo.m_lpsSource[4] = lpsBlock + (6 * 64 * 4);
    StoreInfo.m_lpbDestination[4] = m_lpDestination +
                                    (((i + 4) % m_nMaxNumberOfDIFSequences) * m_nPitch * lSuperBlockHeight411 +
                                    m_nPitch * lMacroBlockHeight411 * lRowC +
                                    ((18) * lMacroBlockWidth411 +
                                    lMacroBlockWidth411 * lColA) * lBytesPerPixel) / m_lSizeSubSampled;


} // void DVVideoDecoder::InitializeStoreDV25Info(STORE_DV_SEGMENT_INFO &StoreInfo,


void DVVideoDecoder::StoreDVSDSegment(Ipp32u i, Ipp32u k, Ipp32u nThreadNum)
{
    STORE_DV_SEGMENT_INFO RealStoreInfo;

    // reset pointers
    InitializeStoreDVSDInfo(RealStoreInfo, i, k, nThreadNum);

    // Store system 525 DV segment
    if (SYSTEM_525 == m_nSystem)
    {
        if (24 <= k)
        {

            ippiYCrCb411ToYCbCr422_EdgeDV_16s8u_P3C2R((Ipp16s *) RealStoreInfo.m_lpsSource[4],
                                                      RealStoreInfo.m_lpbDestination[4],
                                                      (Ipp32u) RealStoreInfo.m_lPitch);

            RealStoreInfo.m_lpbDestination[4] = NULL;
            RealStoreInfo.m_lpsSource[4] = NULL;
        }


        ippiYCrCb411ToYCbCr422_5MBDV_16s8u_P3C2R((const Ipp16s **) RealStoreInfo.m_lpsSource,
                                                 RealStoreInfo.m_lpbDestination,
                                                 (Ipp32u) RealStoreInfo.m_lPitch);

    }
    else
    {

        ippiYCrCb420ToYCbCr422_5MBDV_16s8u_P3C2R((const Ipp16s **) RealStoreInfo.m_lpsSource,
                                                 RealStoreInfo.m_lpbDestination,
                                                 (Ipp32u) RealStoreInfo.m_lPitch);
    }

} // void DVVideoDecoder::StoreDVSegment(Ipp32u i, Ipp32u k, Ipp32u nThreadNum)

void DVVideoDecoder::StoreDV25Segment(Ipp32u i, Ipp32u k, Ipp32u nThreadNum)
{
    STORE_DV_SEGMENT_INFO RealStoreInfo;

    // reset pointers
    InitializeStoreDV25Info(RealStoreInfo, i, k, nThreadNum);

    // Store system 525 DV segment (system 625 has equal storing structure)
    if (24 <= k)
    {
        ippiYCrCb411ToYCbCr422_EdgeDV_16s8u_P3C2R((Ipp16s *) RealStoreInfo.m_lpsSource[4],
                                                  RealStoreInfo.m_lpbDestination[4],
                                                  (Ipp32u) RealStoreInfo.m_lPitch);

        RealStoreInfo.m_lpbDestination[4] = NULL;
        RealStoreInfo.m_lpsSource[4] = NULL;
    }

    ippiYCrCb411ToYCbCr422_5MBDV_16s8u_P3C2R((const Ipp16s **) RealStoreInfo.m_lpsSource,
                                             RealStoreInfo.m_lpbDestination,
                                             (Ipp32u) RealStoreInfo.m_lPitch);

} // void DVVideoDecoder::StoreDV25Segment(Ipp32u i, Ipp32u k, Ipp32u nThreadNum)

} // end namespace UMC

#endif //(UMC_ENABLE_DV_VIDEO_DECODER)
